home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / illustrt / illustrt.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  27KB  |  779 lines

  1. /*****************************************************************************
  2. * Program to create illustrations of wireframe drawings.             *
  3. *   Usually the output of this program is piped to irit2ps, although it      *
  4. * creates a regular IRIT data files with polylines.                 *
  5. *                                         *
  6. * Written by:  Gershon Elber                Ver 1.0, June 1993   *
  7. *****************************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include <math.h>
  11. #include <string.h>
  12. #include "program.h"
  13. #include "config.h"
  14. #include "iritgrap.h"
  15. #include "allocate.h"
  16. #include "poly_cln.h"
  17. #include "geomat3d.h"
  18. #include "getarg.h"
  19. #include "ip_cnvrt.h"
  20.  
  21. #define HEAT_CRV_NUM_PTS    9
  22.  
  23. #ifdef NO_CONCAT_STR
  24. static char *VersionStr =
  25.     "Illustrt        Version 5.0,    Gershon Elber,\n\
  26.      (C) Copyright 1989/90-95 Gershon Elber, Non commercial use only.";
  27. #else
  28. static char *VersionStr =
  29.     "Illustrt        " VERSION ",    Gershon Elber,    "
  30.     __DATE__ ",   " __TIME__ "\n" COPYRIGHT ", Non commercial use only.";
  31. #endif /* NO_CONCAT_STR */
  32.  
  33. static char *CtrlStr =
  34. #ifdef DOUBLE
  35.     "Illustrt I%-#IsoLines!d f%-PolyOpti|SampPerCrv!d!d s%- M%- P%- p%- l%-MaxLnLen!F a%- t%-TrimInter!F o%-OutName!s Z%-InterSameZ!F m%- z%- DFiles!*s";
  36. #else
  37.     "Illustrt I%-#IsoLines!d f%-PolyOpti|SampPerCrv!d!d s%- M%- P%- p%- l%-MaxLnLen!f a%- t%-TrimInter!f o%-OutName!s Z%-InterSameZ!f m%- z%- DFiles!*s";
  38. #endif
  39.  
  40. static char
  41.     *GlblOutFileName = "illustrt.dat";
  42.  
  43. static int
  44.     GlblTalkative = FALSE,
  45.     GlblSortOutput = FALSE,
  46.     GlblPolylineOptiApprox = 0,
  47.     GlblDrawSurfaceMesh = FALSE,
  48.     GlblDrawSurface = TRUE,
  49.     GlblNumOfIsolines = IG_DEFAULT_NUM_OF_ISOLINES,
  50.     GlblSamplesPerCurve = IG_DEFAULT_SAMPLES_PER_CURVE;
  51.  
  52. static RealType
  53.     GlblMaxLineLen = DEFAULT_MAX_LINE_LEN;
  54.  
  55. int GlblAngularDistance = TRUE,
  56.     GlblVertexPoints = FALSE,
  57.     GlblSplitLongLines = FALSE;
  58.  
  59. RealType
  60.     GlblInterSameZ = INTER_SAME_Z,
  61.     GlblTrimIntersect = DEFAULT_TRIM_INTERSECT;
  62.  
  63. static MatrixType CrntViewMat;            /* This is the current view! */
  64.  
  65. static ConfigStruct SetUp[] =
  66. {
  67.   { "NumOfIsolines",  "-I", (VoidPtr) &GlblNumOfIsolines,    SU_INTEGER_TYPE },
  68.   { "PolyOpti",       "-f", (VoidPtr) &GlblPolylineOptiApprox,SU_INTEGER_TYPE },
  69.   { "SamplesPerCurve","-f", (VoidPtr) &GlblSamplesPerCurve,  SU_INTEGER_TYPE },
  70.   { "SortOutput",     "-s", (VoidPtr) &GlblSortOutput,         SU_BOOLEAN_TYPE },
  71.   { "DrawSurfaceMesh","-M", (VoidPtr) &GlblDrawSurfaceMesh,  SU_BOOLEAN_TYPE },
  72.   { "DrawSurface",    "-P", (VoidPtr) &GlblDrawSurface,         SU_BOOLEAN_TYPE },
  73.   { "VertexPoints",   "-p", (VoidPtr) &GlblVertexPoints,     SU_BOOLEAN_TYPE },
  74.   { "AngularDist",    "-a", (VoidPtr) &GlblAngularDistance,  SU_BOOLEAN_TYPE },
  75.   { "MoreVerbose",    "-m", (VoidPtr) &GlblTalkative,         SU_BOOLEAN_TYPE },
  76.   { "InterSameZ",     "-Z", (VoidPtr) &GlblInterSameZ,         SU_REAL_TYPE }
  77. };
  78. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  79.  
  80. static void DumpData(char *FileName,
  81.              IPObjectStruct *NoProcessObjs,
  82.              IPObjectStruct *PObjects);
  83. static IPObjectStruct *ProcessSpeedWave(IPObjectStruct *PObj,
  84.                     char *SpeedWaveAttrs);
  85. static IPPolygonStruct *GenSpeedWave(RealType Coords[3],
  86.                      RealType GenRand,
  87.                      RealType Dir[3],
  88.                      RealType Len,
  89.                      RealType Dist,
  90.                      RealType LenRand,
  91.                      RealType DistRand);
  92. static IPObjectStruct *ProcessHeatWave(IPObjectStruct *PObj,
  93.                        char *HeatWaveAttrs);
  94. static CagdCrvStruct *GenHeatWave(RealType Coords[3],
  95.                   RealType GenRand,
  96.                   RealType Len,
  97.                   RealType Dist,
  98.                   RealType LenRand,
  99.                   RealType DistRand);
  100.  
  101. /*****************************************************************************
  102. * DESCRIPTION:                                                               M
  103. * Main module of illustrt - Read command line and do what is needed...         M
  104. *                                                                            *
  105. * PARAMETERS:                                                                M
  106. *   argc, argv:  Command line.                                               M
  107. *                                                                            *
  108. * RETURN VALUE:                                                              M
  109. *   void                                                                     M
  110. *                                                                            *
  111. * KEYWORDS:                                                                  M
  112. *   main                                                                     M
  113. *****************************************************************************/
  114. void main(int argc, char **argv)
  115. {
  116.     int Error,
  117.     NumOfIsolinesFlag = FALSE,
  118.     CrvOptiPolylinesFlag = FALSE,
  119.         TrimInterFlag = FALSE,
  120.     OutFileFlag = FALSE,
  121.     InterSameZFlag = FALSE,
  122.     VerFlag = FALSE,
  123.     NumFiles = 0;
  124.     char
  125.     **FileNames = NULL;
  126.     IPObjectStruct *PObjects, *NoProcessObjs, *PObj,
  127.     *PObjWaves = NULL;
  128.  
  129.     Config("illustrt", SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  130.  
  131.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  132.                &NumOfIsolinesFlag, &GlblNumOfIsolines,
  133.                &CrvOptiPolylinesFlag, &GlblPolylineOptiApprox,
  134.                &GlblSamplesPerCurve,
  135.                &GlblSortOutput, &GlblDrawSurfaceMesh,
  136.                &GlblDrawSurface, &GlblVertexPoints,
  137.                &GlblSplitLongLines, &GlblMaxLineLen,
  138.                &GlblAngularDistance,
  139.                &TrimInterFlag, &GlblTrimIntersect,
  140.                &OutFileFlag, &GlblOutFileName,
  141.                &InterSameZFlag, &GlblInterSameZ, &GlblTalkative,
  142.                &VerFlag, &NumFiles, &FileNames)) != 0) {
  143.     GAPrintErrMsg(Error);
  144.     GAPrintHowTo(CtrlStr);
  145.     IllustrateExit(1);
  146.     }
  147.  
  148.     if (VerFlag) {
  149.     fprintf(stderr, "\n%s\n\n", VersionStr);
  150.     GAPrintHowTo(CtrlStr);
  151.     ConfigPrint(SetUp, NUM_SET_UP);
  152.     IllustrateExit(0);
  153.     }
  154.  
  155.     if (!NumFiles) {
  156.     fprintf(stderr, "No data file names where given, exit.\n");
  157.     GAPrintHowTo(CtrlStr);
  158.     IllustrateExit(1);
  159.     }
  160.  
  161.     /* Get the data files: */
  162.     if ((PObjects = IritPrsrGetDataFiles(FileNames, NumFiles, TRUE, FALSE)) ==
  163.                                     NULL)
  164.     IllustrateExit(0);
  165.  
  166.     if (IritPrsrWasPrspMat)
  167.     MatMultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  168.     else
  169.     GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
  170.  
  171.     /* Scan the objects for wave supported attributes. */
  172.     for (PObj = PObjects; PObj != NULL; PObj = PObj -> Pnext) {
  173.     IPObjectStruct *PObjWave;
  174.     char *p;
  175.  
  176.     if ((p = AttrGetObjectStrAttrib(PObj, "speedwave")) != NULL &&
  177.         (PObjWave = ProcessSpeedWave(PObj, p)) != NULL) {
  178.         PObjWave -> Pnext = PObjWaves;
  179.         PObjWaves = PObjWave;
  180.     }
  181.     if ((p = AttrGetObjectStrAttrib(PObj, "heatwave")) != NULL &&
  182.         (PObjWave = ProcessHeatWave(PObj, p)) != NULL) {
  183.         PObjWave -> Pnext = PObjWaves;
  184.         PObjWaves = PObjWave;
  185.     }
  186.     }
  187.  
  188.     PObj = GMTransformObjectList(PObjects, CrntViewMat);
  189.     IPFreeObjectList(PObjects);
  190.     PObjects = PObj;
  191.  
  192.     if (PObjWaves != NULL) {
  193.     PObj = GMTransformObjectList(PObjWaves, CrntViewMat);
  194.     IPFreeObjectList(PObjWaves);
  195.     PObjWaves = PObj;
  196.     }
  197.  
  198.     for (PObj = PObjects, PObjects = NoProcessObjs = NULL; PObj != NULL; ) {
  199.     IPObjectStruct
  200.         *PObjNext = PObj -> Pnext;
  201.  
  202.     if (AttrGetObjectStrAttrib(PObj, "IllustrtNoProcess") != NULL) {
  203.         PObj -> Pnext = NoProcessObjs;
  204.         NoProcessObjs = PObj;
  205.     }
  206.     else {
  207.         PObj -> Pnext = PObjects;
  208.         PObjects = PObj;
  209.     }
  210.  
  211.     PObj = PObjNext;
  212.     }
  213.  
  214.     if (GlblVertexPoints) {
  215.     /* Add vertices of each polyline as points into data set. */
  216.     for (PObj = PObjects; PObj != NULL;) {
  217.         if (IP_IS_POLY_OBJ(PObj)) {
  218.         IPObjectStruct
  219.             *PtList = CopyObject(NULL, PObj, TRUE);
  220.  
  221.         IP_SET_POINTLIST_OBJ(PtList);
  222.  
  223.         RemoveInternalVertices(PtList);
  224.  
  225.         PObj -> Pnext = PtList;
  226.         PObj = PtList -> Pnext;
  227.         }
  228.         else
  229.         PObj = PObj -> Pnext;
  230.     }
  231.     }
  232.  
  233.     ProcessIntersections(PObjects);
  234.     if (GlblSplitLongLines)
  235.     SplitLongLines(PObjects, GlblMaxLineLen);
  236.  
  237.     if (GlblSortOutput)
  238.     SortOutput(&PObjects);
  239.  
  240.     /* Append the objects created to represent waves. */
  241.     PObj = IritPrsrGetLastObj(PObjects);
  242.     PObj -> Pnext = PObjWaves;
  243.  
  244.     DumpData(OutFileFlag ? GlblOutFileName : NULL, NoProcessObjs, PObjects);
  245.  
  246.     IllustrateExit(0);
  247. }
  248.  
  249. /*****************************************************************************
  250. * DESCRIPTION:                                                               M
  251. * Routine to convert all surfaces/curves into polylines as follows:         M
  252. *   Curve is converted to a single polyline with SamplesPerCurve samples.    M
  253. *   Surface is converted into GlblNumOfIsolines curves in each axes, each    M
  254. * handled as Curve above. The original curves and surfaces are then deleted. M
  255. *   This function is a call back function of the irit parser.             M
  256. *                                                                            *
  257. * PARAMETERS:                                                                M
  258. *   FreeForms:  Crvs/Srfs/Trimmed Srfs/Trivariates read from a file by the   M
  259. *               irit parser.                                 M
  260. *                                                                            *
  261. * RETURN VALUE:                                                              M
  262. *   IPObjectStruct *:   Processed freeform geometry. This function simply    M
  263. *                       returns what it gots.                                M
  264. *                                                                            *
  265. * KEYWORDS:                                                                  M
  266. *   IritPrsrProcessFreeForm, conversion                                      M
  267. *****************************************************************************/
  268. IPObjectStruct *IritPrsrProcessFreeForm(IritPrsrFreeFormStruct *FreeForms)
  269. {
  270.     CagdCrvStruct *Crv, *Crvs;
  271.     CagdSrfStruct *Srf, *Srfs;
  272.     IPObjectStruct *PObj,
  273.     *CrvObjs = FreeForms -> CrvObjs,
  274.     *SrfObjs = FreeForms -> SrfObjs;
  275.     IPPolygonStruct *PPolygon, *PPolygonTemp;
  276.  
  277.     if (CrvObjs == NULL && SrfObjs == NULL)
  278.     return NULL;
  279.  
  280.     /* Make sure requested format is something reasonable. */
  281.     if (GlblNumOfIsolines < 2) {
  282.     GlblNumOfIsolines = 2;
  283.     fprintf(stderr, "NumOfIsolines is less than 2, 2 picked instead.\n");
  284.     }
  285.  
  286.     if (GlblSamplesPerCurve < 2) {
  287.     GlblSamplesPerCurve = 2;
  288.     fprintf(stderr,
  289.         "SamplesPerCurve is less than 2, 2 picked instead.\n");
  290.     }
  291.  
  292.     if (CrvObjs) {
  293.     for (PObj = CrvObjs; PObj != NULL; PObj = PObj -> Pnext) {
  294.         if (GlblTalkative)
  295.         fprintf(stderr, "Processing curve object \"%s\"\n",
  296.             PObj -> Name);
  297.  
  298.         Crvs = PObj -> U.Crvs;
  299.         PObj -> U.Pl = NULL;
  300.         PObj -> ObjType = IP_OBJ_POLY;
  301.         IP_SET_POLYLINE_OBJ(PObj);
  302.         for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) {
  303.         PPolygon = PPolygonTemp =
  304.             IritCurve2Polylines(Crv, GlblSamplesPerCurve,
  305.                     GlblPolylineOptiApprox);
  306.  
  307.         if (PPolygon != NULL) {
  308.             while (PPolygonTemp -> Pnext)
  309.             PPolygonTemp = PPolygonTemp -> Pnext;
  310.             PPolygonTemp -> Pnext = PObj -> U.Pl;
  311.             PObj -> U.Pl = PPolygon;
  312.         }
  313.         }
  314.         CagdCrvFreeList(Crvs);
  315.     }
  316.     }
  317.  
  318.     if (SrfObjs) {
  319.     int NumOfIso[2];
  320.  
  321.     NumOfIso[0] = -GlblNumOfIsolines;
  322.     NumOfIso[1] = -GlblNumOfIsolines;
  323.  
  324.     for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  325.         if (GlblTalkative)
  326.         fprintf(stderr, "Processing surface object \"%s\"\n",
  327.             PObj -> Name);
  328.         
  329.         Srfs = PObj -> U.Srfs;
  330.         PObj -> U.Pl = NULL;
  331.         PObj -> ObjType = IP_OBJ_POLY;
  332.         IP_SET_POLYLINE_OBJ(PObj);
  333.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  334.         PPolygon = PPolygonTemp =
  335.             IritSurface2Polylines(Srf, NumOfIso,
  336.                       GlblSamplesPerCurve,
  337.                       GlblPolylineOptiApprox);
  338.  
  339.         if (PPolygon != NULL) {
  340.             while (PPolygonTemp -> Pnext)
  341.             PPolygonTemp = PPolygonTemp -> Pnext;
  342.             PPolygonTemp -> Pnext = PObj -> U.Pl;
  343.             PObj -> U.Pl = PPolygon;
  344.         }
  345.         }
  346.         CagdSrfFreeList(Srfs);
  347.     }
  348.     }
  349.  
  350.     if (SrfObjs == NULL)
  351.     return CrvObjs;
  352.     else if (CrvObjs == NULL)
  353.     return SrfObjs;
  354.     else {
  355.     for (PObj = SrfObjs; PObj -> Pnext != NULL; PObj = PObj -> Pnext);
  356.     PObj -> Pnext = CrvObjs;
  357.     return SrfObjs;
  358.     }
  359. }
  360.  
  361. /*****************************************************************************
  362. * DESCRIPTION:                                                               *
  363. * Dumps the data out into FileName (stdout in NULL).                 *
  364. *                                                                            *
  365. * PARAMETERS:                                                                *
  366. *   FileName:        Where output should go to.                              *
  367. *   NoProcessObjs:   List of object that are piped through from input stream *
  368. *             unprocessed.                                            *
  369. *   PObjects:        List of processed object to dump out.                   *
  370. *                                                                            *
  371. * RETURN VALUE:                                                              *
  372. *   void                                                                     *
  373. *****************************************************************************/
  374. static void DumpData(char *FileName,
  375.              IPObjectStruct *NoProcessObjs,
  376.              IPObjectStruct *PObjects)
  377. {
  378.     FILE *f;
  379.  
  380.     if (FileName != NULL) {
  381.     if ((f = fopen(FileName, "w")) == NULL) {
  382.         fprintf(stderr, "Failed to open \"%s\".\n", FileName);
  383.         IllustrateExit(2);
  384.     }
  385.     }
  386.     else
  387.     f = stdout;
  388.  
  389.     fprintf(f, "\tIrit Solid Modeller Data File (ILLUSTRT), %s\n\n",
  390.         IritRealTimeDate());
  391.  
  392.     while (PObjects) {
  393.     /* Dump only polys with at least two vertices and points/vectors. */
  394.     if (IP_IS_POLY_OBJ(PObjects)) {
  395.         if (IP_IS_POLYLINE_OBJ(PObjects))
  396.         CleanUpPolylineList(&PObjects -> U.Pl);
  397.         if (PObjects -> U.Pl != NULL)
  398.         IritPrsrPutObjectToFile(f, PObjects);
  399.     }
  400.     else if (IP_IS_POINT_OBJ(PObjects) ||
  401.          IP_IS_VEC_OBJ(PObjects) ||
  402.          IP_IS_CRV_OBJ(PObjects)) {
  403.         IritPrsrPutObjectToFile(f, PObjects);
  404.     }
  405.  
  406.     PObjects = PObjects -> Pnext;
  407.     }
  408.  
  409.     while (NoProcessObjs) {
  410.     IritPrsrPutObjectToFile(f, NoProcessObjs);
  411.  
  412.     NoProcessObjs = NoProcessObjs -> Pnext;
  413.     }
  414.  
  415.     fclose(f);
  416. }
  417.  
  418. /*****************************************************************************
  419. * DESCRIPTION:                                                               *
  420. * Creates an object representing speed wave from object PObj. SpeedWaveAttr  *
  421. * Holds the attributes of the speed wave in the following format:         *
  422. * "GenRand,DirX,DirY,DirZ,Len,Dist,LenRand,DistRand,Width" with             *
  423. * See GenSpeedWave below.                             *
  424. *                                                                            *
  425. * PARAMETERS:                                                                *
  426. *   PObj:               Object for which a speed wave it to be generated.    *
  427. *   SpeedWaveAttrs:     String describing a speed wave.                      *
  428. *                                                                            *
  429. * RETURN VALUE:                                                              *
  430. *   IPObjectStruct *:   Object representing a speed wave.             *
  431. *****************************************************************************/
  432. static IPObjectStruct *ProcessSpeedWave(IPObjectStruct *PObj,
  433.                     char *SpeedWaveAttrs)
  434. {
  435.     int i, NumPoints;
  436.     char StrLineWidth[LINE_LEN];
  437.     RealType **Points, GenRand, Dir[3], Len, Dist, LenRand, DistRand, Width;
  438.     CagdSrfStruct
  439.     *Srf = NULL;
  440.     CagdCrvStruct
  441.     *Crv = NULL;
  442.     IPObjectStruct *PObjTmp,  *PObjWave;
  443.     IPPolygonStruct *P, *PWave;
  444.  
  445. #ifdef DOUBLE
  446.     if (sscanf(SpeedWaveAttrs, "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf",
  447. #else
  448.     if (sscanf(SpeedWaveAttrs, "%f,%f,%f,%f,%f,%f,%f,%f,%f",
  449. #endif /* DOUBLE */
  450.            &GenRand, &Dir[0], &Dir[1], &Dir[2], &Len,
  451.            &Dist, &LenRand, &DistRand, &Width) != 9) {
  452.     fprintf(stderr, "Wrong parameters of speed wave. Ignored.\n");
  453.     return NULL;
  454.     }
  455.  
  456.     PObjWave = IPAllocObject("SpeedWave", IP_OBJ_POLY, NULL);
  457.     sprintf(StrLineWidth, "%f", Width);
  458.     AttrSetObjectStrAttrib(PObjWave, "width", StrLineWidth);
  459.     IP_SET_POLYLINE_OBJ(PObjWave);
  460.  
  461.     switch (PObj -> ObjType) {
  462.     case IP_OBJ_LIST_OBJ:
  463.         for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
  464.         ProcessSpeedWave(PObjTmp, SpeedWaveAttrs);
  465.         break;
  466.     case IP_OBJ_POLY:
  467.         for (P = PObj -> U.Pl; P != NULL; P = P -> Pnext) {
  468.         IPVertexStruct
  469.             *V = P -> PVertex;
  470.  
  471.         do {
  472.             if ((PWave = GenSpeedWave(V -> Coord, GenRand, Dir, Len,
  473.                       Dist, LenRand, DistRand)) != NULL) {
  474.             PWave -> Pnext = PObjWave -> U.Pl;
  475.             PObjWave -> U.Pl = PWave;
  476.             }
  477.  
  478.             V = V -> Pnext;
  479.         }
  480.         while (V != NULL && V != P -> PVertex);
  481.         }
  482.         break;
  483.     case IP_OBJ_SURFACE:
  484.     case IP_OBJ_CURVE:
  485.         if (PObj -> ObjType == IP_OBJ_SURFACE) {
  486.         Srf = CagdCoerceSrfTo(PObj -> U.Srfs, CAGD_PT_E3_TYPE);
  487.  
  488.         Points = Srf -> Points;
  489.         NumPoints = Srf -> ULength * Srf -> VLength;
  490.         }
  491.         else {
  492.         Crv = CagdCoerceCrvTo(PObj -> U.Crvs, CAGD_PT_E3_TYPE);
  493.  
  494.         Points = Crv -> Points;
  495.         NumPoints = Crv -> Length;
  496.         }
  497.  
  498.         for (i = 0; i < NumPoints; i++) {
  499.         int j;
  500.         RealType Coords[3];
  501.  
  502.         for (j = 0; j < 3; j++)
  503.             Coords[j] = Points[j + 1][i];
  504.  
  505.         if ((PWave = GenSpeedWave(Coords, GenRand, Dir, Len,
  506.                       Dist, LenRand, DistRand)) != NULL) {
  507.             PWave -> Pnext = PObjWave -> U.Pl;
  508.             PObjWave -> U.Pl = PWave;
  509.         }
  510.         }
  511.  
  512.         if (PObj -> ObjType == IP_OBJ_SURFACE)
  513.         CagdSrfFree(Srf);
  514.         else
  515.         CagdCrvFree(Crv);
  516.         break;
  517.     default:
  518.         break;
  519.     }
  520.  
  521.     if (PObjWave -> U.Pl != NULL)
  522.     return PObjWave;
  523.     else {
  524.     IPFreeObject(PObjWave);
  525.     return NULL;
  526.     }
  527. }
  528.  
  529. /*****************************************************************************
  530. * DESCRIPTION:                                                               *
  531. * Randomly generates a single speed wave instance.                 *
  532. *                                                                            *
  533. * PARAMETERS:                                                                *
  534. *   Coords:             Location for which the wave is to be generated.      *
  535. *   GenRand:            Probability of generating the wave.             *
  536. *   Dir:                Direction of wave.                     *
  537. *   Len, Dist:          Length of the wave and distance from object.         *
  538. *   LenRand, DistRand:  Pertubation amount Len and Dist.             *
  539. *                                                                            *
  540. * RETURN VALUE:                                                              *
  541. *   IPPolygonStruct *:  An object representing one speed wave object         *
  542. *                       in probability GenRand, NULL otherwise.              *
  543. *****************************************************************************/
  544. static IPPolygonStruct *GenSpeedWave(RealType Coords[3],
  545.                      RealType GenRand,
  546.                      RealType Dir[3],
  547.                      RealType Len,
  548.                      RealType Dist,
  549.                      RealType LenRand,
  550.                      RealType DistRand)
  551. {
  552.     VectorType DirCopy;
  553.     IPVertexStruct *V1, *V2;
  554.     IPPolygonStruct *P;
  555.  
  556.     /* Test if probability is in favor. */
  557.     if (IritRandom(0.0, 1.0) > GenRand)
  558.     return NULL;
  559.  
  560.     V2 = IPAllocVertex(0, 0, NULL, NULL);
  561.     V1 = IPAllocVertex(0, 0, NULL, V2);
  562.     P = IPAllocPolygon(0, 0, V1, NULL);
  563.  
  564.     PT_COPY(DirCopy, Dir);
  565.     PT_NORMALIZE(DirCopy);
  566.     Dist += DistRand * IritRandom(-1.0, 1.0);
  567.     PT_SCALE(DirCopy, Dist);
  568.     PT_COPY(V1 -> Coord, Coords);
  569.     PT_ADD(V1 -> Coord, V1 -> Coord, DirCopy);
  570.  
  571.     PT_COPY(DirCopy, Dir);
  572.     PT_NORMALIZE(DirCopy);
  573.     Len += LenRand * IritRandom(-1.0, 1.0);
  574.     PT_SCALE(DirCopy, Len);
  575.     PT_COPY(V2 -> Coord, V1 -> Coord);
  576.     PT_ADD(V2 -> Coord, V2 -> Coord, DirCopy);
  577.  
  578.     return P;
  579. }
  580.  
  581. /*****************************************************************************
  582. * DESCRIPTION:                                                               *
  583. * Creates an object representing heat wave from object PObj. HeatWaveAttr    *
  584. * Holds the attributes of the heat wave in the following format:         *
  585. * "GenRand,Len,Dist,LenRand,DistRand,Width" with                 *
  586. * See GenHeatWave below.                             *
  587. *                                                                            *
  588. * PARAMETERS:                                                                *
  589. *   PObj:               Object for which a heat wave it to be generated.     *
  590. *   SpeedWaveAttrs:     String describing a heat wave.                       *
  591. *                                                                            *
  592. * RETURN VALUE:                                                              *
  593. *   IPObjectStruct *:   Object representing a heat wave.             *
  594. *****************************************************************************/
  595. static IPObjectStruct *ProcessHeatWave(IPObjectStruct *PObj,
  596.                        char *HeatWaveAttrs)
  597. {
  598.     int i, NumPoints;
  599.     RealType **Points, GenRand, Len, Dist, LenRand, DistRand, Width;
  600.     CagdSrfStruct
  601.     *Srf = NULL;
  602.     CagdCrvStruct *PWave,
  603.     *Crv = NULL;
  604.     IPObjectStruct *PObjTmp, *PObjWave;
  605.     IPPolygonStruct *P;
  606.  
  607. #ifdef DOUBLE
  608.     if (sscanf(HeatWaveAttrs, "%lf,%lf,%lf,%lf,%lf,%lf",
  609. #else
  610.     if (sscanf(HeatWaveAttrs, "%f,%f,%f,%f,%f,%f",
  611. #endif /* DOUBLE */
  612.            &GenRand, &Len, &Dist, &LenRand, &DistRand, &Width) != 6) {
  613.     fprintf(stderr, "Wrong parameters of heat wave. Ignored.\n");
  614.     return NULL;
  615.     }
  616.  
  617.     PObjWave = IPAllocObject("HeatWave", IP_OBJ_CURVE, NULL);
  618.     AttrSetObjectRealAttrib(PObjWave, "width", Width);
  619.  
  620.     switch (PObj -> ObjType) {
  621.     case IP_OBJ_LIST_OBJ:
  622.         for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
  623.         ProcessHeatWave(PObjTmp, HeatWaveAttrs);
  624.         break;
  625.     case IP_OBJ_POLY:
  626.         for (P = PObj -> U.Pl; P != NULL; P = P -> Pnext) {
  627.         IPVertexStruct
  628.             *V = P -> PVertex;
  629.  
  630.         do {
  631.             if ((PWave = GenHeatWave(V -> Coord, GenRand, Len,
  632.                       Dist, LenRand, DistRand)) != NULL) {
  633.             PWave -> Pnext = PObjWave -> U.Crvs;
  634.             PObjWave -> U.Crvs = PWave;
  635.             }
  636.  
  637.             V = V -> Pnext;
  638.         }
  639.         while (V != NULL && V != P -> PVertex);
  640.         }
  641.         break;
  642.     case IP_OBJ_SURFACE:
  643.     case IP_OBJ_CURVE:
  644.         if (PObj -> ObjType == IP_OBJ_SURFACE) {
  645.         Srf = CagdCoerceSrfTo(PObj -> U.Srfs, CAGD_PT_E3_TYPE);
  646.  
  647.         Points = Srf -> Points;
  648.         NumPoints = Srf -> ULength * Srf -> VLength;
  649.         }
  650.         else {
  651.         Crv = CagdCoerceCrvTo(PObj -> U.Crvs, CAGD_PT_E3_TYPE);
  652.  
  653.         Points = Crv -> Points;
  654.         NumPoints = Crv -> Length;
  655.         }
  656.  
  657.         for (i = 0; i < NumPoints; i++) {
  658.         int j;
  659.         RealType Coords[3];
  660.  
  661.         for (j = 0; j < 3; j++)
  662.             Coords[j] = Points[j + 1][i];
  663.  
  664.         if ((PWave = GenHeatWave(Coords, GenRand, Len,
  665.                      Dist, LenRand, DistRand)) != NULL) {
  666.             PWave -> Pnext = PObjWave -> U.Crvs;
  667.             PObjWave -> U.Crvs = PWave;
  668.         }
  669.         }
  670.  
  671.         if (PObj -> ObjType == IP_OBJ_SURFACE)
  672.         CagdSrfFree(Srf);
  673.         else
  674.         CagdCrvFree(Crv);
  675.         break;
  676.     default:
  677.         break;
  678.     }
  679.  
  680.     if (PObjWave -> U.Pl != NULL)
  681.     return PObjWave;
  682.     else {
  683.     IPFreeObject(PObjWave);
  684.     return NULL;
  685.     }
  686. }
  687.  
  688. /*****************************************************************************
  689. * DESCRIPTION:                                                               *
  690. * Randomly generates a single heat wave instance.                 *
  691. *                                                                            *
  692. * PARAMETERS:                                                                *
  693. *   Coords:             Location for which the wave is to be generated.      *
  694. *   GenRand:            Probability of generating the wave.             *
  695. *   Len, Dist:          Length of the wave and distance from object.         *
  696. *   LenRand, DistRand:  Pertubation amount Len and Dist.             *
  697. *                                                                            *
  698. * RETURN VALUE:                                                              *
  699. *   CagdCrvStruct *:    An object representing one heat wave object          *
  700. *                       in probability GenRand, NULL otherwise.              *
  701. *****************************************************************************/
  702. static CagdCrvStruct *GenHeatWave(RealType Coords[3],
  703.                   RealType GenRand,
  704.                   RealType Len,
  705.                   RealType Dist,
  706.                   RealType LenRand,
  707.                   RealType DistRand)
  708. {
  709.     static VectorType
  710.     HeatCtlPts[HEAT_CRV_NUM_PTS] =
  711.     {
  712.         { 0.0, 0.0, 0.0 },
  713.         { 0.1, 0.0, 0.25 },
  714.         { 0.0, 0.1, 0.3 },
  715.         { 0.0, 0.0, 0.2 },
  716.         { 0.1, 0.0, 0.35 },
  717.         { 0.0, 0.0, 0.5 },
  718.         { 0.0, 0.0, 0.35 },
  719.         { 0.1, 0.1, 0.5 },
  720.         { 0.1, 0.0, 0.6 },
  721.     };
  722.     int i, j;
  723.     CagdCrvStruct *Crv;
  724.  
  725.     /* Test if probability is in favor. */
  726.     if (IritRandom(0.0, 1.0) > GenRand)
  727.     return NULL;
  728.  
  729.     Len += LenRand * IritRandom(-1.0, 1.0);
  730.     Dist += DistRand * IritRandom(-1.0, 1.0);
  731.  
  732.     Crv = BspCrvNew(HEAT_CRV_NUM_PTS, 3, CAGD_PT_E3_TYPE);
  733.     BspKnotUniformOpen(HEAT_CRV_NUM_PTS, 3, Crv -> KnotVector);
  734.     for (i = 0; i < HEAT_CRV_NUM_PTS; i++)
  735.     for (j = 0; j < 3; j++)
  736.         Crv -> Points[j + 1][i] = Coords[j] + (j == 2 ? Dist : 0.0) + 
  737.         HeatCtlPts[i][j] * Len;
  738.  
  739.     return Crv;
  740. }
  741.  
  742. /*****************************************************************************
  743. * DESCRIPTION:                                                               M
  744. * Illustrt Exit routine.                             M
  745. *                                                                            *
  746. * PARAMETERS:                                                                M
  747. *   ExitCode:    To notify O.S. with result of program.                      M
  748. *                                                                            *
  749. * RETURN VALUE:                                                              M
  750. *   void                                                                     M
  751. *                                                                            *
  752. * KEYWORDS:                                                                  M
  753. *   IllustrateExit                                                           M
  754. *****************************************************************************/
  755. void IllustrateExit(int ExitCode)
  756. {
  757.     exit(ExitCode);
  758. }
  759.  
  760. #ifdef DEBUG
  761.  
  762. /*****************************************************************************
  763. * DESCRIPTION:                                                               *
  764. *    Dummy function to link at debugging time.                               *
  765. *                                                                            *
  766. * PARAMETERS:                                                                *
  767. *                                                                            *
  768. * RETURN VALUE:                                                              *
  769. *   void                                                                     *
  770. *                                                                            *
  771. * KEYWORDS:                                                                  *
  772. *****************************************************************************/
  773. void DummyLinkCagdDebug(void)
  774. {
  775.     IritPrsrDbg();
  776. }
  777.  
  778. #endif /* DEBUG */
  779.